package project.parser.ast.exps;

import project.environments.DynamicEnv;
import project.environments.StaticEnv;
import project.environments.Value;
import project.parser.TypecheckException;
import project.parser.ast.types.Type;

import static project.parser.tokenizer.TokenType.ASSGN;
import static project.parser.tokenizer.TokenType.SEMI_COL;

public class Assign implements Exp {
	private final Exp id;
	private final Exp exp;

	public Assign(Exp id, Exp exp) {
		this.id = id;
		this.exp = exp;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder().append(id).append(ASSGN)
				.append(exp).append(SEMI_COL);
		return sb.toString();
	}

	@Override
	public Type typecheck(StaticEnv senv) {
		if (!(id instanceof Ident) && !(id instanceof FieldAccess))
			throw new TypecheckException("Expected an identifier in assignment expression");
		Type type = exp.typecheck(senv);
		if (id instanceof FieldAccess)
			((FieldAccess)id).set(senv, type);
		else
			senv.update((Ident)id, type);
		return type;
	}

	@Override
	public Value evaluate(DynamicEnv denv) {
		Value idValue = id.evaluate(denv);
		Value assignValue = exp.evaluate(denv);
		if (id instanceof FieldAccess)
			((FieldAccess)id).set(denv, assignValue); //set del campo per i record
		else
			denv.update((Ident)id, assignValue); //update dell'ambiente dinamico per le variabili
		return assignValue;
	}
}
